package com.example.sys.module.service.impl;

import cn.hutool.core.util.ClassUtil;
import com.example.core.form.BaseForm;
import com.example.sys.module.annotation.SysField;
import com.example.sys.module.annotation.SysModule;
import com.example.sys.module.mode.SysColumnInfo;
import com.example.sys.module.mode.SysModuleInfo;
import com.example.sys.module.service.SysModuleRoleService;
import com.example.sys.module.service.SysModuleService;
import com.example.sys.org.model.SysOrgRole;
import com.example.sys.org.service.SysOrgRoleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.*;

@Service
public class SysModuleServiceImpl implements SysModuleService, ApplicationListener<ContextRefreshedEvent> {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private List<SysModuleRoleService> sysModuleRoleServices = new ArrayList<>();

    @Resource
    private SysOrgRoleService sysOrgRoleService;

    @Value("${default.roleAlias}")
    private String roleAlias;

    @Value("${default.title}")
    private String defaultTitle;

    private List<SysModuleInfo> sysModuleInfos = new ArrayList<>();

    @Override
    public List<SysModuleInfo> loadModuleInfos() {
        List<SysModuleInfo> sysModuleInfos = new ArrayList<>();
        Set<Class<?>> classSet = ClassUtil.scanPackage();
        for (Class<?> formClass : classSet) {
            if (BaseForm.class.isAssignableFrom(formClass) && formClass.isAnnotationPresent(SysModule.class)) {
                SysModule sysModule = formClass.getAnnotation(SysModule.class);
                SysModuleInfo sysModuleInfo = new SysModuleInfo();
                sysModuleInfo.setComment(sysModule.comment());
                sysModuleInfo.setEntityClass(sysModule.entityClass());
                sysModuleInfo.setFormClass(formClass);
                Field[] fields = formClass.getDeclaredFields();
                for (Field field : fields) {
                    if (field.isAnnotationPresent(SysField.class)) {
                        SysField sysField = field.getAnnotation(SysField.class);
                        SysColumnInfo sysColumnInfo = new SysColumnInfo();
                        sysColumnInfo.setComment(sysField.comment());
                        sysColumnInfo.setProperty(field.getName());
                        sysModuleInfo.getColumnInfos().add(sysColumnInfo);
                    }
                }
                sysModuleInfos.add(sysModuleInfo);
            }
        }
        return sysModuleInfos;
    }

    @Override
    public void loadModuleAuthMaps(Map<String, String> map) {
        for (SysModuleInfo sysModuleInfo : this.getSysModuleInfos()) {
            for (SysModuleRoleService sysModuleRoleService : this.sysModuleRoleServices) {
                sysModuleRoleService.loadRoleMap(map, sysModuleInfo);
            }
        }
    }

    @Override
    public List<SysModuleInfo> getSysModuleInfos() {
        if (this.sysModuleInfos.isEmpty()) {
            this.sysModuleInfos = this.loadModuleInfos();
        }
        return this.sysModuleInfos;
    }

    @Override
    public SysModuleInfo getSysModuleInfoByShortName(String shortName) {
        for (SysModuleInfo sysModuleInfo : this.sysModuleInfos) {
            if (sysModuleInfo.getShortName().equals(shortName)) {
                return sysModuleInfo;
            }
        }
        return null;
    }

    @Override
    public SysModuleInfo getSysModuleInfoBySimpleName(String entityName) {
        for (SysModuleInfo sysModuleInfo : this.sysModuleInfos) {
            if (sysModuleInfo.getSimpleName().equals(entityName)) {
                return sysModuleInfo;
            }
        }
        return null;
    }

    @Override
    public void initRoles() throws Exception {
        List<SysModuleInfo> sysModuleInfos = this.getSysModuleInfos();
        for (SysModuleInfo sysModuleInfo : sysModuleInfos) {
            for (SysModuleRoleService sysModuleRoleService : this.sysModuleRoleServices) {
                Map<String, String> roleMap = sysModuleRoleService.getRoleMap(sysModuleInfo);
                for (String roleCode : roleMap.keySet()) {
                    SysOrgRole sysOrgRole = this.sysOrgRoleService.getRoleByCode(roleCode);
                    if (sysOrgRole == null) {
                        sysOrgRole = new SysOrgRole();
                        sysOrgRole.setFdCode(roleCode);
                        sysOrgRole.setFdName(sysModuleInfo.getComment() + roleMap.get(roleCode));
                        this.sysOrgRoleService.add(sysOrgRole);
                    }
                }
                SysOrgRole baseRole = this.sysOrgRoleService.getRoleByCode(sysModuleInfo.getBaseRole());
                if (baseRole == null) {
                    baseRole = new SysOrgRole();
                    baseRole.setFdCode(sysModuleInfo.getBaseRole());
                    baseRole.setFdName(sysModuleInfo.getComment() + roleAlias);
                    this.sysOrgRoleService.add(baseRole);
                }
            }
        }
    }

    @Override
    public String getDefaultTitle() {
        return this.defaultTitle;
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (event.getApplicationContext().getParent() == null) {
            try {
                this.initRoles();
            } catch (Exception e) {
                logger.warn("初始化角色信息异常：{}", e.getMessage());
            }
        }
    }
}